package com.licheedev.glide_qrcode;

import android.graphics.Bitmap;
import android.graphics.Color;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.bumptech.glide.Glide;
import com.licheedev.context.AppProvider;
import java.util.Objects;

public class QrCode {

    private String qr = "unknown";
    private int size = 500;
    private String charSet = "UTF-8";
    private String errorCorrection = "L";
    private int margin = 1;
    private int contentColor = Color.BLACK;
    private int backgroundColor = Color.WHITE;
    private float logoPercent = 0.2f;
    private Object logo = null;
    private Object contentReplace = null;
    private boolean isImageUrl = false;
    private int logoBackgroundColor = 0;
    private boolean toLogoLogo = true;

    private static final BitmapFetcher DEFAULT_BITMAP_FETCHER = new DefaultBitmapFetcher();
    @NonNull
    private BitmapFetcher bitmapFetcher = DEFAULT_BITMAP_FETCHER;

    /** 默认的Bitmap加载器 */
    public static class DefaultBitmapFetcher implements BitmapFetcher {
        @Nullable
        @Override
        public Bitmap toBitmap(@Nullable Object source) throws Exception {
            if (source == null) {
                return null;
            }

            if (source instanceof Bitmap) {
                return (Bitmap) source;
            }

            return Glide.with(AppProvider.INSTANCE.getApplication())
                .asBitmap()
                .load(source)
                .submit()
                .get();
        }
    }

    public interface BitmapFetcher {
        @Nullable
        Bitmap toBitmap(@Nullable Object source) throws Exception;
    }

    /**
     * 二维码对象
     *
     * @param qr 二维码内容
     */
    public QrCode(String qr) {
        if (!TextUtils.isEmpty(qr)) {
            this.qr = qr;
        }
    }

    /**
     * 二维码对象
     *
     * @param qr 二维码内容
     * @param isImageUrl 二维码是否为图片url
     */
    public QrCode(String qr, boolean isImageUrl) {
        if (!TextUtils.isEmpty(qr)) {
            this.qr = qr;
        }
        this.isImageUrl = isImageUrl;
    }

    /** 创建二维码 */
    @NonNull
    public static QrCode wrap(String qr) {
        return new QrCode(qr);
    }

    /**
     * 创建二维码
     *
     * @param qr
     * @param isImageUrl 二维码是否为图片url
     * @return
     */
    @NonNull
    public static QrCode wrap(String qr, boolean isImageUrl) {
        return new QrCode(qr, isImageUrl);
    }

    /** 二维码内容 */
    @NonNull
    public String getQr() {
        return qr;
    }

    /** 二维码内容 */
    @NonNull
    public QrCode setQr(String qr) {
        if (!TextUtils.isEmpty(qr)) {
            this.qr = qr;
        }
        return this;
    }

    /**
     * 设置二维码
     *
     * @param qr 二维码内容
     * @param isImageUrl 二维码是否为图片url
     * @return
     */
    @NonNull
    public QrCode setQr(String qr, boolean isImageUrl) {
        if (!TextUtils.isEmpty(qr)) {
            this.qr = qr;
        }
        this.isImageUrl = isImageUrl;
        return this;
    }

    /** 二维码尺寸 */
    public int getSize() {
        return size;
    }

    /** 二维码尺寸 */
    @NonNull
    public QrCode setSize(int size) {
        this.size = size;
        return this;
    }

    /** 编码方式（一般使用UTF-8） */
    @NonNull
    public String getCharSet() {
        return charSet;
    }

    /** 编码方式（一般使用UTF-8） */
    @NonNull
    public QrCode setCharSet(@NonNull String charSet) {
        this.charSet = charSet;
        return this;
    }

    /** 容错率 L：7% M：15% Q：25% H：35% */
    @NonNull
    public QrCode L() {
        errorCorrection = "L";
        return this;
    }

    /** 容错率 L：7% M：15% Q：25% H：35% */
    @NonNull
    public QrCode M() {
        errorCorrection = "M";
        return this;
    }

    /** 容错率 L：7% M：15% Q：25% H：35% */
    @NonNull
    public QrCode Q() {
        errorCorrection = "Q";
        return this;
    }

    /** 容错率 L：7% M：15% Q：25% H：35% */
    public QrCode H() {
        errorCorrection = "H";
        return this;
    }

    /** 容错率 L：7% M：15% Q：25% H：35% */
    public String getErrorCorrection() {
        return errorCorrection;
    }

    /** 空白边距（二维码与边框的空白区域） */
    public int getMargin() {
        return margin;
    }

    /** 空白边距（二维码与边框的空白区域） */
    @NonNull
    public String getMarginText() {
        return String.valueOf(margin);
    }

    /** 空白边距（二维码与边框的空白区域） */
    @NonNull
    public QrCode setMargin(int margin) {
        this.margin = margin;
        return this;
    }

    /** 作为内容的黑色色块 */
    public int getContentColor() {
        return contentColor;
    }

    /** 作为内容的黑色色块 */
    @NonNull
    public QrCode setContentColor(int contentColor) {
        this.contentColor = contentColor;
        return this;
    }

    /** 作为背景的白色色块 */
    public int getBackgroundColor() {
        return backgroundColor;
    }

    /** 作为背景的白色色块 */
    @NonNull
    public QrCode setBackgroundColor(int backgroundColor) {
        this.backgroundColor = backgroundColor;
        return this;
    }

    /** logo百分比 */
    public float getLogoPercent() {
        return logoPercent;
    }

    /** logo百分比 */
    @NonNull
    public QrCode setLogoPercent(float logoPercent) {
        this.logoPercent = logoPercent;
        return this;
    }

    /**
     * logo
     *
     * @param logo 可以是bitmap，资源id，uri等
     */
    @NonNull
    public QrCode setLogo(@Nullable Object logo) {
        this.logo = logo;
        return this;
    }

    /**
     * logo
     *
     * @return
     */
    @Nullable
    public Object getLogo() {
        return logo;
    }

    /**
     * logo背景颜色，如果为0，则不画
     *
     * @param logoBackgroundColor logo背景颜色，如果为0，则不画
     */
    public QrCode setLogoBackgroundColor(int logoBackgroundColor) {
        this.logoBackgroundColor = logoBackgroundColor;
        return this;
    }

    /** logo背景颜色，如果为0，则不画 */
    public int getLogoBackgroundColor() {
        return logoBackgroundColor;
    }

    /**
     * 作为内容（黑色色块）的替换对象，可以是bitmap，资源id，uri等
     *
     * @return
     */
    @Nullable
    public Object getContentReplace() {
        return contentReplace;
    }

    /**
     * 作为内容（黑色色块）的替换对象
     *
     * @param contentReplace 可以是bitmap，资源id，uri等
     */
    @NonNull
    public QrCode setContentReplace(@Nullable Object contentReplace) {
        this.contentReplace = contentReplace;
        return this;
    }

    /**
     * {@link #qr} 内容是否为图片url
     *
     * @return 默认false
     */
    public boolean isImageUrl() {
        return isImageUrl;
    }

    /**
     * 配置 {@link #qr} 内容是否为图片url
     *
     * @param isImageUrl 二维码是否为图片url
     */
    @NonNull
    public QrCode setIsImageUrl(boolean isImageUrl) {
        this.isImageUrl = isImageUrl;
        return this;
    }

    /**
     * 是否要加载logo图片
     *
     * @return
     */
    public boolean isToLogoLogo() {
        return toLogoLogo;
    }

    /**
     * 配置是否要加载logo图片
     *
     * @param toLogoLogo
     */
    public QrCode setToLogoLogo(boolean toLogoLogo) {
        this.toLogoLogo = toLogoLogo;
        return this;
    }

    /**
     * logo等字段转bitmap
     *
     * @return
     */
    @NonNull
    public BitmapFetcher getBitmapFetcher() {
        return bitmapFetcher;
    }

    /**
     * logo等字段转bitmap
     *
     * @param bitmapFetcher
     * @return
     */
    @NonNull
    public QrCode setBitmapFetcher(@NonNull BitmapFetcher bitmapFetcher) {
        this.bitmapFetcher = bitmapFetcher;
        return this;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        QrCode code = (QrCode) o;
        return size == code.size
            && margin == code.margin
            && contentColor == code.contentColor
            && backgroundColor == code.backgroundColor
            && Float.compare(code.logoPercent, logoPercent) == 0
            && isImageUrl == code.isImageUrl
            && toLogoLogo == code.toLogoLogo
            && qr.equals(code.qr)
            && charSet.equals(code.charSet)
            && errorCorrection.equals(code.errorCorrection)
            && Objects.equals(logo, code.logo)
            && logoBackgroundColor == code.logoBackgroundColor
            && Objects.equals(contentReplace, code.contentReplace)
            && bitmapFetcher.equals(code.bitmapFetcher);
    }

    @Override
    public int hashCode() {
        return Objects.hash(qr, size, charSet, errorCorrection, margin, contentColor,
            backgroundColor, logoPercent, logo, logoBackgroundColor, contentReplace, isImageUrl,
            toLogoLogo, bitmapFetcher);
    }

    @Override
    public String toString() {
        return "QrCode{"
            + "qr='"
            + qr
            + '\''
            + ", size="
            + size
            + ", charSet='"
            + charSet
            + '\''
            + ", errorCorrection='"
            + errorCorrection
            + '\''
            + ", margin="
            + margin
            + ", contentColor="
            + contentColor
            + ", backgroundColor="
            + backgroundColor
            + ", logoPercent="
            + logoPercent
            + ", logo="
            + logo
            + ", contentReplace="
            + contentReplace
            + ", isImageUrl="
            + isImageUrl
            + ", toLogoLogo="
            + toLogoLogo
            + ", logoBackgroundColor="
            + logoBackgroundColor
            + ", bitmapFetcher="
            + bitmapFetcher
            + '}';
    }
}